import re
import os

import dep_graph.keys

class Error(Exception):
  """Root Level Exception"""

class RootMissingError(Error):
  """ Could not find the .build_config file of the repo """

class RuleNameError(Error):
  """Invalid rule name."""

_pathed_dep = re.compile("//([^:]*):([^:]+)$")
_pathed_dep1 = re.compile("([^:]+):([^:]+)$")
_pathed_dep2 = re.compile(":([^:]+)$")
_pathed_dep3 = re.compile("([^:\\\\/]+)$")

def adjust_rule(cwd, rulename):
  match = _pathed_dep.match(rulename, 0)
  if match:
    if len(match.group(1)) == 0:
      base_path = "."
    else:
      base_path = os.path.relpath(match.group(1))
      if base_path == ".":
        base_path = "."
    return "//" + base_path + ":" + match.group(2)
  match = _pathed_dep2.match(rulename, 0)
  if match:
    return "//" + cwd + rulename

def adjust_rule_with_relative_paths(cwd, rulename):
  if len(cwd) == 0:
    cwd = "."

  match = _pathed_dep3.match(rulename, 0)
  if(match):
    return "//" + cwd + ":" + rulename
  
  val = adjust_rule(cwd, rulename)
  if (val != None):
    return val
  match = _pathed_dep1.match(rulename, 0)
  if match:
    base_path = os.path.relpath(os.path.join(cwd, match.group(1)))
    if base_path == ".":
      base_path = "."
    return "//" + base_path + ":" + match.group(2)
  raise RuleNameError('Invalid rule name %s' % repr(rulename))

def find_root():
  root_folder = os.getcwd()
  rule_adjust = []
  while not os.access(os.path.join(root_folder, ".build_config"), os.F_OK):
    if root_folder == "/":
      raise RootMissingError("No .build_config found! Please add one")
    rule_adjust.append(os.path.basename(root_folder))
    root_folder = os.path.dirname(root_folder)

  if len(rule_adjust) > 1:
    rule_adjust = os.path.join(*reversed(rule_adjust))
  elif len(rule_adjust) == 1:
    rule_adjust = rule_adjust[0]
  elif len(rule_adjust) == 0:
    rule_adjust = ""
  return root_folder, rule_adjust

def ensure_path(path):
  path = os.path.realpath(path)
  if path == "/":
    return
  ensure_path(os.path.dirname(path))
  if not os.access(path, os.F_OK):
    os.mkdir(path)

_pathed_file = re.compile('//([^:]*)')
def repo_rel(cwd, fname):
  match = _pathed_file.match(fname)
  if match:
    return os.path.relpath(match.group(1))
  else:
    return os.path.relpath(os.path.join(cwd, fname))

def repo_to_pair(full_path):
  name = os.path.basename(full_path)
  fname = os.path.dirname(full_path)
  if fname == '':
    fname = '.'
  return (fname, name)

def getPathConsts(fname):
  lib_dir = os.path.dirname(os.path.realpath(__file__))
  BUILD_ROOT, rule_adjust = find_root()
  os.chdir(BUILD_ROOT)
  return BUILD_ROOT, rule_adjust, lib_dir

def pathToKey(name, variant, cwd = '.'):
  rulename = adjust_rule_with_relative_paths(cwd, name)
  dirname, name = _pathed_dep.match(rulename, 0).groups()
  return dep_graph.keys.GenRuleKey(dirname, name, variant)

_recursive_rules = re.compile('^(\/\/)?(([^/]+\/)*)\.\.\.$')

def wildcardToKeyIter(name, variant, cwd, graph):
  mtch = _recursive_rules.match(name, 0)
  if mtch:
    absolute, path, _ = mtch.groups()
    if len(cwd) == 0:
      cwd = '.'
    if len(path) == 0:
      path = '.'
    else:
      path = path[:-1]
    if not absolute:
      if path == '.':
        path = cwd
      elif cwd != '.':
        path = cwd + '/' + path[:-1]
    return graph.getRecursiveRules(path, variant)
